package com.xbongbong.pro.statistic.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.BIProductEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.HomePageCustomTypeEnum;
import com.xbongbong.paas.enums.ScreenTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.vo.IsActiveAliyunCallVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.domain.entity.ChartCategoryEntity;
import com.xbongbong.pro.domain.entity.ChartCategorySearchEntity;
import com.xbongbong.pro.domain.entity.ChartCategoryTextEntity;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.domain.entity.ChartFavoriteEntity;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.StatisticsServicesErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.global.ChartCategoryEnum;
import com.xbongbong.pro.enums.permission.enums.ChartProPermissionAliasEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.form.pojo.HomePagePoJo;
import com.xbongbong.pro.form.pojo.dto.HomePageDeleteDTO;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.permission.pojo.dto.VerifyDeletePermissionDTO;
import com.xbongbong.pro.service.toolbox.statistic.help.ChartPermissionHelp;
import com.xbongbong.pro.statistic.constant.ChartConstant;
import com.xbongbong.pro.statistic.enums.CategoryEnum;
import com.xbongbong.pro.statistic.enums.ChartCategoryAliasEnum;
import com.xbongbong.pro.statistic.enums.ChartCategoryTypeEnum;
import com.xbongbong.pro.statistic.enums.ChartPublishEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.enums.StatisticsTypeEnum;
import com.xbongbong.pro.statistic.enums.SystemCodeEnum;
import com.xbongbong.pro.statistic.help.ChartInitHelp;
import com.xbongbong.pro.statistic.help.CustomHelp;
import com.xbongbong.pro.statistic.manager.feign.PaasFormFeignClient;
import com.xbongbong.pro.statistic.model.ChartCategoryModel;
import com.xbongbong.pro.statistic.model.ChartCategorySearchModel;
import com.xbongbong.pro.statistic.model.ChartCategoryTextModel;
import com.xbongbong.pro.statistic.model.ChartCustomModel;
import com.xbongbong.pro.statistic.model.ChartFavoriteModel;
import com.xbongbong.pro.statistic.model.ChartModel;
import com.xbongbong.pro.statistic.pojo.ChartCategoryQueryPojo;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.pojo.ChartPkFormPojo;
import com.xbongbong.pro.statistic.pojo.dto.CategoryFieldGetDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategoryPermissionSaveDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategoryPublishDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategorySearchGetDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategorySearchGetListDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategorySearchSaveBatchDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategorySearchSaveDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategoryTextGetDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategoryTextGetListDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategoryTextSaveDTO;
import com.xbongbong.pro.statistic.pojo.dto.CategoryUpgradeDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartCategoryDeleteDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartCategoryEnableDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartCategoryFormDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartCategoryGetDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartCategoryInitDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartCategoryListDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartCategorySaveDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartCategorySortDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartCategorySortInfoDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartInitDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartListDTO;
import com.xbongbong.pro.statistic.pojo.dto.ChartMobileCategoryListDTO;
import com.xbongbong.pro.statistic.pojo.vo.CategoryFieldGetVO;
import com.xbongbong.pro.statistic.pojo.vo.CategorySearchGetListVO;
import com.xbongbong.pro.statistic.pojo.vo.CategorySearchGetVO;
import com.xbongbong.pro.statistic.pojo.vo.CategorySearchVO;
import com.xbongbong.pro.statistic.pojo.vo.CategoryTextGetListVO;
import com.xbongbong.pro.statistic.pojo.vo.CategoryTextGetVO;
import com.xbongbong.pro.statistic.pojo.vo.CategoryTextVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartBaseInfoVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategoryDeleteVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategoryEnableVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategoryFormVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategoryGetVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategoryIndexDetailVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategoryIndexListVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategoryInitVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategoryListVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategorySaveVO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategorySortVO;
import com.xbongbong.pro.statistic.pojo.vo.DataSourceObjectVO;
import com.xbongbong.pro.statistic.result.pojo.dto.ChartCategoryListByIdInDTO;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartCategoryListByIdInVO;
import com.xbongbong.pro.statistic.service.ChartCategoryService;
import com.xbongbong.pro.statistic.service.ChartCategoryTextService;
import com.xbongbong.pro.statistic.service.ChartLimitService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.product.ContractProductBIEnum;
import com.xbongbong.saas.model.HomePageManageModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.UserConfigEntity;
import com.xbongbong.sys.enums.UserConfigEnum;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.FeeLogModel;
import com.xbongbong.sys.model.UserConfigModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import static java.util.Comparator.comparingInt;

/**
 * 报表分类相关
 *
 * @author zcp
 * @date 2019/1/11
 * @since v1.0
 * @version v1.0
 */
@Service("chartCategoryService")
public class ChartCategoryServiceImpl implements ChartCategoryService {

    private static final Logger LOG = LoggerFactory.getLogger(ChartCategoryServiceImpl.class);

    /**
     * 默认权限信息
     */
    private static final String PERMISSION_CUSTOM_MSG = "{\"visible\": 0, \"visibleScopeRule\": {\"dep\": [], \"role\": [], \"type\": 2, \"user\": []}, \"visibleScopeEnable\": 0}";
    private static final String PERMISSION_OTHER_MSG = "{\"visible\": 1, \"visibleScopeRule\": {\"dep\": [], \"role\": [], \"type\": 2, \"user\": []}, \"visibleScopeEnable\": 0}";
    private static final String PERMISSION_VISIBLE_EXPORT_MSG = "{\"export\": 1, \"visible\": 1, \"exportRule\": {\"dep\": [], \"role\": [], \"type\": 2, \"user\": []}, \"visibleScopeRule\": {\"dep\": [], \"role\": [], \"type\": 2, \"user\": []}, \"visibleScopeEnable\": 0, \"exportAdvanceEnable\": 0}";

    @Resource
    private ChartCategoryModel chartCategoryModel;
    @Resource
    private ChartModel chartModel;
    @Resource
    private ChartCustomModel chartCustomModel;
    @Resource
    private ChartFavoriteModel chartFavoriteModel;
    @Resource
    private ChartInitHelp chartInitHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private ChartPermissionHelp chartPermissionHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private UserConfigModel userConfigModel;
    @Resource
    private ChartCategorySearchModel chartCategorySearchModel;
    @Resource
    private ChartCategoryTextModel chartCategoryTextModel;
    @Resource
    private CustomHelp customHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasFormFeignClient paasFormFeignClient;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private AliyuncallCenterServiceImpl  aliyuncallCenterService;
    @Resource
    private ChartCategoryTextService chartCategoryTextService;
    @Resource
    private ChartLimitService chartLimitService;
    @Resource
    private ChartCategoryService chartCategoryService;
    @Resource
    private HomePageManageModel homePageManageModel;
    @Resource
    private FeeLogModel feeLogModel;


    @Override
    public List<ChartCategoryEntity> getChartCategoryList(ChartCategoryQueryPojo chartCategoryQueryPojo) {
        if (chartCategoryQueryPojo == null) {
            return new ArrayList<>();
        }
        String corpid = chartCategoryQueryPojo.getCorpid();
        //分类id数组
        Set<Long> idIn = chartCategoryQueryPojo.getIdIn();
        //报表类型
        List<Integer> typeIn = chartCategoryQueryPojo.getTypeIn();
        typeIn.add(-1);
        //父分类id数组
        Set<Long> parentIdIn = chartCategoryQueryPojo.getParentIdIn();
        //是否开启，不传则获取全部
        Integer enable = chartCategoryQueryPojo.getEnable();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (Objects.equals(chartCategoryQueryPojo.getGetUpgradeFlag(), BasicConstant.ONE)) {
            typeIn.remove(new Integer(ChartCategoryTypeEnum.DASHBOARD.getCode()));
        }
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("typeIn", typeIn);
        param.put("enable", enable);
        if (idIn.size() > 0) {
            param.put("idIn", idIn);
        }
        if (parentIdIn.size() > 0) {
            param.put("parentIdIn", parentIdIn);
        }
        //排序规则：sort降序、id升序
        String sortStr = "sort DESC, id ASC";
        param.put("orderByStr", sortStr);
        return chartCategoryModel.findEntitys(param);
    }

    @Override
    public ChartCategoryIndexListVO chartCategoryIndexList(ChartCategoryListDTO chartCategoryListDTO) throws XbbException {
        String corpid = chartCategoryListDTO.getCorpid();
        //web首页左、右侧，图表中心系统，图表中心自定义
        List<Integer> typeIn = ChartCategoryTypeEnum.getCodeList4WebIndex();
        List<Integer> homeTypeIn = ChartCategoryTypeEnum.getCodeList4Home();
        List<Integer> homeCenterTypeIn = ChartCategoryTypeEnum.getCodeList4HomeCenter();
        ChartCategoryQueryPojo chartCategoryQueryPojo = new ChartCategoryQueryPojo();
        //为chartCategorySearchDto赋值corpid等基础信息
        BeanUtil.copyProperties(chartCategoryListDTO, chartCategoryQueryPojo);
        chartCategoryQueryPojo.setTypeIn(typeIn);
        chartCategoryQueryPojo.setEnable(1);
        List<ChartCategoryEntity> list = getChartCategoryList(chartCategoryQueryPojo);
        boolean marketShow = checkMarketEnable(chartCategoryListDTO, XbbRefTypeEnum.MARKET_MANAGEMENT.getAlias());
        //拥有图表的分类id数组：首页右侧、左侧id，图表中心二级分类的分类id
        Set<Long> supCategoryIdIn = new HashSet<>();
        //父分类id--分类vo的list
        Map<Long, List<ChartCategoryIndexDetailVO>> childMap = new HashMap<>(list.size());
        //父分类list：首页左侧
        List<ChartCategoryIndexDetailVO> left = new ArrayList<>();
        //父分类list：图表中心系统、自定义
        List<ChartCategoryIndexDetailVO> center = new ArrayList<>();
        //父分类list：首页右侧
        List<ChartCategoryIndexDetailVO> right = new ArrayList<>();
        //父分类list：图表中心系统、自定义(存自定义图)
        List<ChartCategoryIndexDetailVO> customCenter = new ArrayList<>();
        //权限
        UserVO loginUser = chartCategoryListDTO.getLoginUser();
        Set<String> saasPermissions = loginUser.getPermSet();
        List<String> strings = Arrays.asList("saleClue", "marketActivityAnalysis", "clueAnalysis", "pkUserLeadConverAnalysis");
        //经销商管理相关部分不展示
        List<String> distributorManagement = Arrays.asList("distributorManagement", "salesAnalysis", "deliveryAnalysis");
        for (ChartCategoryEntity entity : list) {
            if (marketShow) {
                if (strings.contains(entity.getAlias())) {
                    continue;
                }
            }
            if (distributorManagement.contains(entity.getAlias())) {
                continue;
            }
            Integer type = entity.getType();
            Long parentId = entity.getParentId();
            //图表中心内的二级分组下面才会有直属图表
            ChartCategoryTypeEnum chartCategoryTypeEnum = ChartCategoryTypeEnum.getEnumByCode(type);
            boolean indexFlag = homeTypeIn.contains(type);
            boolean chartFlag = !parentId.equals(0L) && (homeCenterTypeIn.contains(type));
            if (chartFlag) {
                supCategoryIdIn.add(entity.getId());
            }
            ChartCategoryIndexDetailVO chartCategoryIndexDetailVO = ChartCategoryIndexDetailVO.category2CategoryIndexDetailVO(entity, indexFlag);
            // 如果是访客计划给置灰
            if (Objects.equals(entity.getAlias(),ChartCategoryAliasEnum.COMMUNICATE_PLAN.getAlias())){
                chartCategoryIndexDetailVO.setForbidden(PaasConstant.ENABLE_FORBIDDEN);
            }
            //父分类不为空---肯定都是图表中心二级分类的
            if (!parentId.equals(0L)) {
                //处理子分类
                List<ChartCategoryIndexDetailVO> childList = childMap.get(parentId);
                childList = (childList == null) ? new ArrayList<>() : childList;
                childList.add(chartCategoryIndexDetailVO);
                childMap.put(parentId, childList);
            }else {
                switch (chartCategoryTypeEnum){
                    //首页右侧、左侧
                    case WEB_INDEX_RIGHT:
                        //权限
                        if (!checkRaiders(entity, corpid)) {
                            continue;
                        }
                        if (permission4saas(entity, saasPermissions)) {
                            chartCategoryIndexDetailVO.setStatisticsType(StatisticsTypeEnum.SYSTEM_STATISTIC.getCode());
                            right.add(chartCategoryIndexDetailVO);
                        }
                        break;
                    case WEB_INDEX_LEFT:
                        //权限
                        if (permission4saas(entity, saasPermissions)) {
                            chartCategoryIndexDetailVO.setStatisticsType(StatisticsTypeEnum.SYSTEM_STATISTIC.getCode());
                            left.add(chartCategoryIndexDetailVO);
                        }
                        break;
                    //图表中心一级分类
                    case CHART_CENTER_SYSTEM:
                    case CHART_CENTER_CUSTOM:
                        center.add(chartCategoryIndexDetailVO);
                        break;
                    default:
                        break;
                }
            }
        }
        //分类id---该分类下的所有图表列表
        Map<Long, List<ChartBaseInfoVO>> categoryChartsMap = getSubChart(chartCategoryListDTO, supCategoryIdIn);
        Iterator<ChartCategoryIndexDetailVO> centerIterator = center.iterator();
        //处理图表中心一级分类：塞入二级分类，并为二级分类塞入图表
        while (centerIterator.hasNext()) {
            ChartCategoryIndexDetailVO singleCenter = centerIterator.next();
            ChartCategoryIndexDetailVO singleCustomCenter = (ChartCategoryIndexDetailVO) CloneUtil.deepClone(singleCenter);
            singleCustomCenter.setIsCustom(1);
            //处理二级分类
            List<ChartCategoryIndexDetailVO> childList = childMap.get(singleCenter.getChartCategoryId());
            List<ChartCategoryIndexDetailVO> customChildList = new ArrayList<>();
            if (childList != null && !Objects.equals(childList.size(), BasicConstant.ZERO)) {
                singleCenter.setChildList(childList);
                //处理二级分类的图表
                Iterator<ChartCategoryIndexDetailVO> childIterator = childList.iterator();
                //循环二级分类,如果其下图表不能拖到首页,则删除该二级分类
                while (childIterator.hasNext()) {
                    ChartCategoryIndexDetailVO child = childIterator.next();
                    ChartCategoryIndexDetailVO customChild = (ChartCategoryIndexDetailVO) CloneUtil.deepClone(child);
                    List<ChartBaseInfoVO> chartList = categoryChartsMap.get(child.getChartCategoryId());
                    List<ChartBaseInfoVO> systemChartList = new ArrayList<>();
                    List<ChartBaseInfoVO> customChartList = new ArrayList<>();
                    if (CollectionUtils.isNotEmpty(chartList)){
                        chartList.forEach(chart ->{
                            chart.setSecondCategoryId(child.getChartCategoryId());
                            if (!Objects.equals(child.getCategoryType(),ChartCategoryTypeEnum.DASHBOARD.getCode()) && Objects.equals(chart.getStatisticsType(),StatisticsTypeEnum.SYSTEM_STATISTIC.getCode())){
                                systemChartList.add(chart);
                            } else if (Objects.equals(chart.getStatisticsType(),StatisticsTypeEnum.CUSTOM_STATISTIC.getCode())){
                                customChartList.add(chart);
                            }
                        });
                    }
                    if (systemChartList == null || Objects.equals(systemChartList.size(), BasicConstant.ZERO)) {
                        childIterator.remove();
                    } else {
                        child.setChartList(systemChartList);
                    }
                    if (CollectionUtils.isNotEmpty(customChartList)) {
                        customChild.setChartList(customChartList);
                        customChildList.add(customChild);
                    }
                }
                //如果二级分类下没有图表，则删除一级分类
                if (childList.size() == BasicConstant.ZERO) {
                    centerIterator.remove();
                }
                if (customChildList.size() != BasicConstant.ZERO) {
                    singleCustomCenter.setChildList(customChildList);
                    customCenter.add(singleCustomCenter);
                }
            } else {
                //如果一级分类下没有二级分类，则删除一级分类
                centerIterator.remove();
            }
        }
        // right排序
        defaultRightSort(right);
        //把图表中心的都塞入首页左侧分类下方
        left.addAll(center);
        customCenter.addAll(left);
        left = customCenter;
        ChartCategoryIndexListVO chartCategoryIndexListVO = new ChartCategoryIndexListVO();
        chartCategoryIndexListVO.setLeft(left);
        chartCategoryIndexListVO.setRight(right);
        return chartCategoryIndexListVO;
    }

    private void defaultRightSort(List<ChartCategoryIndexDetailVO> right) {
        Map<String,Integer> sortMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        sortMap.put(ChartCategoryAliasEnum.COMMUNICATE_PLAN.getAlias(),1);
        sortMap.put(ChartCategoryAliasEnum.APPROVAL.getAlias(),2);
        sortMap.put(ChartCategoryAliasEnum.APPROVAL_PROGRESS.getAlias(),3);
        sortMap.put(ChartCategoryAliasEnum.PENDING_WORK_ORDER.getAlias(),4);
        sortMap.put(ChartCategoryAliasEnum.REMIND.getAlias(),5);
        sortMap.put(ChartCategoryAliasEnum.SALES_REPORT.getAlias(),6);
        sortMap.put(ChartCategoryAliasEnum.FORGET_REMIND.getAlias(),7);
        sortMap.put(ChartCategoryAliasEnum.STOCK_WARNING.getAlias(),8);
        sortMap.put(ChartCategoryAliasEnum.DATA_WARNING.getAlias(),9);
        sortMap.put(ChartCategoryAliasEnum.CUSTOMER_CARE.getAlias(),10);
        sortMap.put(ChartCategoryAliasEnum.PENDING_WORK_ORDER_V2.getAlias(),11);
        Map<Long,Integer> categoryIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ChartCategoryIndexDetailVO chartCategoryIndexDetailVO : right) {
            categoryIdMap.put(chartCategoryIndexDetailVO.getChartCategoryId(),sortMap.get(chartCategoryIndexDetailVO.getAlias()));
        }
        right.forEach(item ->{
            item.setSort(categoryIdMap.get(item.getChartCategoryId()));
        });
        Collections.sort(right, new Comparator<ChartCategoryIndexDetailVO>() {
            @Override
            public int compare(ChartCategoryIndexDetailVO o1, ChartCategoryIndexDetailVO o2) {
                if (o1.getSort() == null || o2.getSort() == null){
                    return 1;
                }else if (o1.getSort() >= o2.getSort()){
                    return 1;
                }else {
                    return -1;
                }
            }
        });
    }

    @Override
    public ChartCategoryListVO chartCategoryList(ChartCategoryListDTO chartCategoryListDTO) throws XbbException {
        String corpid = chartCategoryListDTO.getCorpid();
        String userId = chartCategoryListDTO.getUserId();
        //图表中心系统，图表中心自定义
        //TODO 选择已有图表功能中系统图表分类暂时删除，不允许选择
        boolean isGetChart = Objects.equals(chartCategoryListDTO.getGetChartFlag(), 1);
        boolean upgrade = Objects.equals(chartCategoryListDTO.getGetUpgradeFlag(), BasicConstant.ONE);
        // 市场活动关闭,市场活动相关图表移除
        boolean marketShow = checkMarketEnable(chartCategoryListDTO, XbbRefTypeEnum.MARKET_MANAGEMENT.getAlias());
        // 经销商活动关闭，经销商相关图表移除
        boolean distributorShow = checkMarketEnable(chartCategoryListDTO, XbbRefTypeEnum.DISTRIBUTOR.getAlias());
        // 工单2.0图表显隐
        boolean workOrderV2Show = checkMarketEnable(chartCategoryListDTO, XbbRefTypeEnum.WORK_ORDER_V2_CENTER.getAlias());
        List<Integer> typeIn = ChartCategoryTypeEnum.getCodeList4WebChartCenter();
        List<Long> secondCategoryIds = new ArrayList<>();
        ChartCategoryQueryPojo chartCategoryQueryPojo = new ChartCategoryQueryPojo();
        //为chartCategorySearchDto赋值corpid等基础信息
        BeanUtil.copyProperties(chartCategoryListDTO, chartCategoryQueryPojo);
        chartCategoryQueryPojo.setTypeIn(typeIn);
        chartCategoryQueryPojo.setEnable(chartCategoryListDTO.getEnable());
        //根据前端传入的enable获取分类列表，如果enable为null，则获取所有（包含未启用）
        List<ChartCategoryEntity> list = getChartCategoryList(chartCategoryQueryPojo);
        //父分类id--分类vo的list
        Map<Long, List<ChartCategoryListVO>> childMap = new HashMap<>(list.size());
        //所有的父分类vo：首页左右侧、图表中心一级分类
        List<ChartCategoryListVO> supList = new ArrayList<>();
        Map<Long, List<Long>> subAllDepIdMap = departmentModel.getSubDepIdMap(corpid, false);
        Boolean pastDue = feeLogModel.workOrderV2PastDue(corpid);
        for (ChartCategoryEntity entity : list) {
            if (upgrade) {
                //升级仪表盘列表过滤二级分组类型的系统图表
                /*if (entity.getParentId() != 0 && entity.getAlias() != null) {
                    continue;
                }*/
                //过滤pk和目标
                if (entity.getAlias() != null){
                    if (entity.getParentId() != 0 || entity.getAlias().equals(ChartCategoryEnum.PK_USER.getAlias()) || entity.getAlias().equals(ChartCategoryEnum.PERFORMANCE_FINISH_CHART.getAlias())){
                        continue;
                    }
                }
            }
            if (isGetChart) {
                //未升级的二级分组不允许选择已有图表
                if (entity.getParentId() != 0 && Objects.equals(entity.getType(), ChartCategoryTypeEnum.CHART_CENTER_CUSTOM.getCode())) {
                    continue;
                }
            }
            /*List<String> workOrderV2Strings = Arrays.asList("workOrderV2Analysis", "receiptOrderAnalysis");
            if (workOrderV2Strings.contains(entity.getAlias()) && pastDue) {
                continue;
            }*/
            if (Objects.equals("workOrderCompletedAnalysis", entity.getAlias()) && pastDue) {
                continue;
            }
            if (!marketShow){
                List<String> strings = Arrays.asList("saleClue", "marketActivityAnalysis", "clueAnalysis", "pkUserLeadConverAnalysis");
                if (strings.contains(entity.getAlias())){
                    continue;
                }
            }
            if (!distributorShow){
                List<String> strings = Arrays.asList("distributorManagement", "salesAnalysis", "deliveryAnalysis");
                if (strings.contains(entity.getAlias())){
                    continue;
                }
            }
            if (!workOrderV2Show && Objects.nonNull(entity.getAlias()) && (entity.getAlias().contains("workOrderV2") || entity.getAlias().contains("receipt"))){
                //工单2.0关闭时,隐藏相关图表
                continue;
            }
            ChartCategoryListVO chartCategoryListVO = new ChartCategoryListVO();
            BeanUtil.copyProperties(entity, chartCategoryListVO, true);
            /*
             * 图表中心二级分类的父分类id不为空
             * 图表中心内的二级分组下面才会有直属图表
             */
            Long parentId = entity.getParentId();
            if (!parentId.equals(0L)) {
                JSONObject permissions = entity.getPermissions();
                //仪表盘分类权限若为空 默认塞入默认权限信息，处理老数据兼容
                if (permissions == null) {
                    Integer type = entity.getType();
                    if (Objects.equals(type, ChartCategoryTypeEnum.DASHBOARD.getCode())) {
                        permissions = JSON.parseObject(PERMISSION_CUSTOM_MSG);
                    } else {
                        permissions = JSON.parseObject(PERMISSION_OTHER_MSG);
                    }
                    entity.setPermissions(permissions);
                    chartCategoryListVO.setPermissions(permissions);
                }
                //权限判断
                if (!customHelp.judgeCategoryPermissions(permissions, chartCategoryListDTO, subAllDepIdMap)) {
                    continue;
                }
                secondCategoryIds.add(entity.getId());
                //处理子分类
                List<ChartCategoryListVO> childList = childMap.get(parentId);
                if (childList == null) {
                    childList = new ArrayList<>();
                }
                childList.add(chartCategoryListVO);
                childMap.put(parentId, childList);
            }else {
                //图表中心一级分类
                supList.add(chartCategoryListVO);
            }
        }
        //是否还存在需要升级的二级分组
        int upgradeFlag = 0;
        //循环父级的分类，为其塞入子分类
        Iterator<ChartCategoryListVO> iterator = supList.iterator();
        while (iterator.hasNext()) {
            ChartCategoryListVO chartCategoryListVO = iterator.next();
            //处理子分类
            List<ChartCategoryListVO> childList = childMap.get(chartCategoryListVO.getId());
            if (CollectionsUtil.isNotEmpty(childList)) {
                if (!isGetChart) {
                    //二级分组中如果还存在自定义类型分组则表示还存在分类可升级为仪表盘
                    for (ChartCategoryListVO e : childList) {
                        if (Objects.equals(ChartCategoryTypeEnum.CHART_CENTER_CUSTOM.getCode(), e.getType())) {
                            upgradeFlag = 1;
                            break;
                        }
                    }
                }
                if (childList.size() == 0 && isGetChart) {
                    iterator.remove();
                }
                // 判断套餐是否是旗舰版
                Boolean ultimateWithFeeType = packageHelp.isUltimateWithFeeType(corpid);
                // 目标完成情况的特殊处理  如果不是旗舰版则过滤掉自定义目标
                if (Objects.equals(chartCategoryListVO.getAlias(), ChartCategoryEnum.PERFORMANCE_FINISH_CHART.getAlias())){
                    if (!ultimateWithFeeType){
                        childList.removeIf(i-> !Objects.equals(i.getAlias(), ChartCategoryEnum.SYSTEM_PERFORMANCE_CHART.getAlias()));
                    }
                }
                chartCategoryListVO.setChildList(childList);
            } else if (upgrade || isGetChart) {
                //升级仪表盘接口和获取已有图表分类接口 不展示无二级分类的分类
                iterator.remove();
            }
        }

        //当前用户的权限
        UserVO userVO = chartCategoryListDTO.getLoginUser();
        VerifyDeletePermissionDTO permissionDTO = new VerifyDeletePermissionDTO();
        BeanUtil.copyProperties(chartCategoryListDTO,permissionDTO);
        JSONObject obj = new JSONObject();
        //新增 编辑的权限 只在全局设定
        Boolean addPermission = ProPermissionHelp.hasThisPermission(userVO, ChartProPermissionAliasEnum.CHART_ADD.getAlias());
        obj.put(ChartProPermissionAliasEnum.CHART_ADD.getAlias(), ProPermissionHelp.hasThisPermission(userVO, ChartProPermissionAliasEnum.CHART_ADD.getAlias()));
        obj.put(ChartProPermissionAliasEnum.CHART_UPDATE.getAlias(),ProPermissionHelp.hasThisPermission(userVO, ChartProPermissionAliasEnum.CHART_UPDATE.getAlias()));
        obj.put(ChartProPermissionAliasEnum.CHART_PUBLISH.getAlias(),ProPermissionHelp.hasThisPermission(userVO, ChartProPermissionAliasEnum.CHART_PUBLISH.getAlias()));
        //新增图表渲染的环境(true-ck环境，false-es环境)，前端需要用该标记来控制Q3季度需求的显隐
        obj.put("ckFlag",chartLimitService.getCkFlag());
        obj.put("menuSetAble",userVO.isAdminOrBoss());
        Integer feeType = packageHelp.getFeeType(corpid);
        //非免费版非标准版，且有图表新建权限或者老板超管角色，才有新建仪表盘按钮
        boolean addDashboard = !PackageTypeEnum.checkFreeOrStandard(feeType) && (addPermission || userVO.isAdminOrBoss());
        obj.put(ChartProPermissionAliasEnum.ADD_DASHBOARD.getAlias(), addDashboard);
        ChartCategoryListVO result = new ChartCategoryListVO();
        result.setUpgradeFlag(upgradeFlag);
        result.setChartPermissions(obj);
        //具有编辑权限且存在未升级二级分类
        if (obj.getBoolean(ChartProPermissionAliasEnum.CHART_UPDATE.getAlias()) && Objects.equals(upgradeFlag, 1)) {
            long time = System.currentTimeMillis();
            //TODO 时间上线时需要改动，改为上线日期后两周的时间 2020-01-01
            if (time < 1609490662000L){
                result.setDisplayTipsFlag(BasicConstant.ONE);
            }
        }
        result.setChildList(supList);
        // 国际化白名单
        CompanyConfigEntity entity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.I18N_WHITE.getAlias(), PaasConstant.DEFAULT_DATA_CORPID);
        String value = CompanyConfigEnum.I18N_WHITE.getValue();
        if (Objects.nonNull(entity)) {
            value = entity.getConfigValue();
        }
        List<String> whiteList = JsonHelperUtil.parseArray(value, String.class);
        boolean flag = CollectionsUtil.isNotEmpty(whiteList) && whiteList.contains(chartCategoryListDTO.getCorpid());
        result.setMultiLang(flag);

        // 插入与呼叫中心表单
        List<ChartCategoryListVO> childList = result.getChildList();
        IsActiveAliyunCallVO activeAliyunCall = aliyuncallCenterService.isActiveAliyunCall(corpid, userId);
        boolean activeAliyunCall1 = activeAliyunCall.isActiveAliyunCall();
        int role = activeAliyunCall.getRole();
        // 技能组或管理员才有表单,系统管理员无法查看云呼的BI
        if(activeAliyunCall1&&(role==2||role==3) && Objects.equals(0, activeAliyunCall.getFacilitators())){
            // 设置云呼表单
            ChartCategoryListVO chartCategoryList = aliyuncallCenterService.getChartCategoryList();
            childList.add(chartCategoryList);
        }

        return result;
    }

    private boolean checkMarketEnable(ChartCategoryListDTO chartCategoryListDTO, String alias) throws XbbException {
        Boolean enable = false;
        String corpid = chartCategoryListDTO.getCorpid();
        PaasAppEntity paasAppEntity = new PaasAppEntity();
        if (StringUtil.isNotEmpty(alias)) {
            paasAppEntity = paasAppModel.getByAlias(alias, corpid);
        }
        Integer feeType = packageHelp.getFeeType(corpid);
        if (checkAppEnable(paasAppEntity, feeType)){
            enable = true;
        }
        return enable;
    }

    private boolean checkAppEnable(PaasAppEntity paasAppEntity, Integer feeType) {
        return (Objects.nonNull(paasAppEntity) && Objects.equals(paasAppEntity.getEnable(), BasicConstant.ONE));
    }

    /**
     * 图表中心pk榜特殊模版筛选
     *
     * @param chartCategoryFormDTO
     * @return java.util.List<com.xbongbong.pro.statistic.pojo.vo.ChartCategoryListVO>
     * @throws XbbException
     * @author youli.chen
     * @date 2019/1/14 19:21
     * @version v1.0
     * @since v1.0
     */
    @Override
    public ChartCategoryFormVO chartCategoryForm(ChartCategoryFormDTO chartCategoryFormDTO) throws XbbException {
        ChartCategoryFormVO chartCategoryFormVO = new ChartCategoryFormVO();
        List<ChartPkFormPojo> formList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        //查找图表列表
        Map<String, Object> map = BeanUtil.convertBean2Map(chartCategoryFormDTO, true);
        //获取pk类型的图表
        map.put("chartType", ChartTypeEnum.PK.getCode());
        List<ChartEntity> list = chartModel.findEntitys(map);
        if (list == null || list.size() == 0) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224022, I18nMessageUtil.getMessage(I18nStringConstant.REQUEST_PK_LIST_NOT_EXIST));
        }
        Integer businessType = BasicConstant.ZERO;
        for (ChartEntity chartEntity : list) {
            SystemCodeEnum systemCodeEnum = SystemCodeEnum.getByCode(chartEntity.getSystemCode());
            if (systemCodeEnum == null) {
                continue;
            }
            Integer chartType = chartEntity.getChartType();
            String systemCode = chartEntity.getSystemCode();
            if (Objects.equals(chartType, ChartTypeEnum.PK.getCode())) {
                if (Objects.equals(systemCode, SystemCodeEnum.PK_CONTRACT_AMOUNT.getSystemCode()) || Objects.equals(systemCode, SystemCodeEnum.PK_CONTRACT_COUNT.getSystemCode()) ||
                        Objects.equals(systemCode, SystemCodeEnum.PK_CONTRACT_PROFIT.getSystemCode())) {
                    // 合同模版
                    businessType = XbbRefTypeEnum.CONTRACT.getCode();
                } else if (Objects.equals(systemCode, SystemCodeEnum.PK_OPPORTUNITY_ADD_COUNT.getSystemCode()) || Objects.equals(systemCode, SystemCodeEnum.PK_OPPORTUNITY_ADD_AMOUNT.getSystemCode())) {
                    // 机会模版
                    businessType = XbbRefTypeEnum.SALES_OPPORTUNITY.getCode();
                } else if (Objects.equals(systemCode, SystemCodeEnum.PK_CUSTOMER_ADD.getSystemCode())) {
                    // 客户模版
                    businessType = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
                }
            }
        }
        if (!Objects.equals(businessType, BasicConstant.ZERO)) {
            List<PaasFormEntityExt> paasFormEntityExtList = paasFormModel.getEnableFormList(chartCategoryFormDTO.getCorpid(), businessType);
            if (!paasFormEntityExtList.isEmpty()) {
                paasFormEntityExtList.forEach(paasForm -> {
                    ChartPkFormPojo chartPkFormPojo = new ChartPkFormPojo();
                    chartPkFormPojo.setFormId(paasForm.getId());
                    chartPkFormPojo.setFormName(paasForm.getName());
                    formList.add(chartPkFormPojo);
                });
            }
        }
        chartCategoryFormVO.setFormList(formList);
        return chartCategoryFormVO;
    }

    @Override
    public ChartCategoryGetVO chartCategoryGet(ChartCategoryGetDTO chartCategoryGetDTO) throws XbbException {
        String corpid = chartCategoryGetDTO.getCorpid();
        Long id = chartCategoryGetDTO.getId();
        ChartCategoryEntity entity = chartCategoryModel.getByKey(id, corpid);
        if (entity == null) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224034);
        }
        ChartCategoryGetVO chartCategoryGetVO = new ChartCategoryGetVO();
        BeanUtil.copyProperties(entity, chartCategoryGetVO);

        return chartCategoryGetVO;
    }

    @Override
    public ChartCategoryGetVO chartCategoryEdit(ChartCategoryGetDTO chartCategoryGetDTO) throws XbbException {
        //目前edit内获取的东西与get方法一致
        return chartCategoryGet(chartCategoryGetDTO);
    }

    @Override
    public ChartCategorySaveVO chartCategorySave(ChartCategorySaveDTO chartCategorySaveDTO) throws XbbException {
        String corpid = chartCategorySaveDTO.getCorpid();
        String userId = chartCategorySaveDTO.getUserId();
        Long id = chartCategorySaveDTO.getId();
        Long parentId = chartCategorySaveDTO.getParentId();
        String name = chartCategorySaveDTO.getName();
        String nameEn = chartCategorySaveDTO.getNameEn();
        ChartCategoryEntity parent = null;
        if (!parentId.equals(0L)) {
            //传入的父分类id不为空，则需判断父分类是否存在，且判断父分类是不是一级分类
            parent = chartCategoryModel.getByKey(parentId, corpid);
            if (parent == null || parent.getDel() == 1) {
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224035);
            }
            //该分类的父分类必须是一级分类
            if (!parent.getParentId().equals(0L)) {
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224036);
            }
        }
        //接下来处理保存（新建or编辑）
        long now = DateUtil.getInt();
        Integer sort = 0;
        ChartCategoryEntity entity = chartCategoryModel.getByKey(id, corpid);
        String originNameEn = null;
        String logMemoUpdateTemplate;
        OperateTypeEnum operateTypeEnum;
        JSONObject oldObj = null;
        if (entity == null) {
            entity = new ChartCategoryEntity();
            entity.setCorpid(corpid);
            entity.setAddTime(now);
            // 设置新建类型
            if (!parentId.equals(0L)) {
                entity.setPermissions(JSON.parseObject(PERMISSION_CUSTOM_MSG));
                if (Objects.equals(parent.getType(), ChartCategoryTypeEnum.PK_USER.getCode())) {
                    // pk指标新建为自定义pk类型
                    entity.setType(ChartCategoryTypeEnum.PK_CUSTOM.getCode());
                    // 权限默认可见
                    entity.setPermissions(JSON.parseObject(PERMISSION_VISIBLE_EXPORT_MSG));
                }else if (Objects.equals(parent.getType(), ChartCategoryTypeEnum.PERFORMANCE.getCode())) {
                    // pk指标新建为自定义pk类型
                    entity.setType(ChartCategoryTypeEnum.PERFORMANCE_CUSTOM.getCode());
                    // 权限默认可见
                    entity.setPermissions(JSON.parseObject(PERMISSION_VISIBLE_EXPORT_MSG));
                } else {
                    // 二级分组新建类型为仪表盘类型
                    entity.setType(ChartCategoryTypeEnum.DASHBOARD.getCode());
                }
            } else {
                //一级分组新建为自定义类型
                entity.setType(ChartCategoryTypeEnum.CHART_CENTER_CUSTOM.getCode());
            }
            entity.setCreatorId(userId);
            entity.setDel(0);
            entity.setEnable(1);
            entity.setPublish(ChartPublishEnum.NOT_PUBLISH.getCode());
            logMemoUpdateTemplate = I18nMessageUtil.getMessage(LogMemoConstant.CHART_LOG_MEMO_USER_ADD_MENU);
            operateTypeEnum = OperateTypeEnum.NEW;
        }else {
            originNameEn = entity.getNameEn();
            oldObj = JSONObject.parseObject(JSONObject.toJSONString(entity));
            sort = entity.getSort();
            Long oldParentId = entity.getParentId();
            //一二级分类检查
            checkParentId(parentId, oldParentId);
            if (!oldParentId.equals(parentId)) {
                //父分类id变更，即把二级分类拖动到了其他分组，则默认置底
                sort = 0;
            }
            logMemoUpdateTemplate = I18nMessageUtil.getMessage(LogMemoConstant.CHART_LOG_MEMO_USER_UPDATE_MENU);
            operateTypeEnum = OperateTypeEnum.EDIT;
        }
        entity.setParentId(parentId);
        entity.setName(name);
        entity.setNameEn(nameEn);
        entity.setSort(sort);
        entity.setUpdateTime(now);
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("corpid", corpid);
        params.put("del", DelEnum.NORMAL.getDel());
        params.put("typeIn", Arrays.asList(ChartCategoryTypeEnum.CHART_CENTER_CUSTOM.getCode(), ChartCategoryTypeEnum.DASHBOARD.getCode()));
        Integer chartSize = chartCategoryModel.getEntitysCount(params);
        ChartCategorySaveVO chartCategorySaveVO = new ChartCategorySaveVO();
        //创建分组限制
        if(chartSize < ChartConstant.CATEGORY_SIZE_MAX) {
            Map<String, Object> paramsCustomAndSys = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            paramsCustomAndSys.put("corpid", corpid);
            paramsCustomAndSys.put("del", DelEnum.NORMAL.getDel());
            List<Integer> typeIn = new ArrayList<>();
            typeIn.add(ChartCategoryTypeEnum.CHART_CENTER_CUSTOM.getCode());
            typeIn.add(ChartCategoryTypeEnum.CHART_CENTER_SYSTEM.getCode());
            typeIn.add(ChartCategoryTypeEnum.DASHBOARD.getCode());
            typeIn.add(ChartCategoryTypeEnum.PERFORMANCE_CUSTOM.getCode());
            paramsCustomAndSys.put("typeIn", typeIn);
            if(parentId == 0){
                //一级分组
                paramsCustomAndSys.put("parentId", 0);
            }else{
                //二级分组
                paramsCustomAndSys.put("negParentId", 0);
            }
            List<ChartCategoryEntity> chartsCustomAndSys = chartCategoryModel.findEntitys(paramsCustomAndSys);
            //判重逻辑
            Optional<ChartCategoryEntity> optional= chartsCustomAndSys.stream().filter(e -> {
                if (Objects.nonNull(nameEn) && nameEn.equals(e.getNameEn())) {
                    return true;
                }
                return Objects.nonNull(name) && name.equals(e.getName());
            }).findFirst();
            if (optional.isPresent()) {
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224032);
            }
            //英文环境下只修改英文名称会对中文名称覆盖，所以这边特殊处理一下
            Locale locale = LocaleContextHolder.getLocale();
            if (Objects.equals(locale.getLanguage(), I18nStringConstant.ENGLISH_LANGUAGE) && StringUtils.isEmpty(nameEn)) {
                entity.setNameEn(originNameEn);
            }
            chartCategoryModel.save(entity);
            BeanUtil.copyProperties(entity, chartCategorySaveVO);
            // 目标管理两边状态按钮要一致
            if (id != null && Objects.equals(entity.getType(),ChartCategoryTypeEnum.PERFORMANCE_CUSTOM.getCode())){
                List<ChartEntity> chartCustomList = chartCustomModel.getChartListByCategoryId(corpid, id);
                for (ChartEntity chartEntity : chartCustomList) {
                    chartEntity.setName(entity.getName());
                    chartEntity.setUpdateTime(now);
                    chartCustomModel.update(chartEntity);
                }
            }
            String userName = chartCategorySaveDTO.getLoginUserName();
            // 记录日志
            String memo = String.format(logMemoUpdateTemplate, userName, chartCategorySaveDTO.getName());
            JSONObject newObj = JSONObject.parseObject(JSONObject.toJSONString(entity));
            List<DetailLogPojo> detailArr = logHelp.getDetailArr4Normal(corpid, OperateModuleTypeEnum.CHART_CATEGORY, oldObj, newObj);
            mongoLogHelp.buildLog4DetailArr(detailArr, corpid, userId, userName, OperateModuleTypeEnum.CHART_CATEGORY, operateTypeEnum, entity.getId().toString(), chartCategorySaveDTO.getName(), memo, chartCategorySaveDTO.getHttpHeader());
        }else{
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224030, String.format(StatisticsServicesErrorCodeEnum.API_ERROR_224030.getMsg(), ChartConstant.CHART_CATEGORY_SIZE));
        }
        return chartCategorySaveVO;
    }

    @Override
    public ChartCategoryDeleteVO chartCategoryDelete(ChartCategoryDeleteDTO chartCategoryDeleteDTO) throws XbbException {
        String corpid = chartCategoryDeleteDTO.getCorpid();
        Long id = chartCategoryDeleteDTO.getId();
        ChartCategoryEntity entity = chartCategoryModel.getByKey(id, corpid);
        if (entity == null || entity.getDel() == 1) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224034);
        }
        //系统分类不能删除
        if (ChartCategoryTypeEnum.CHART_CENTER_CUSTOM.getCode() != entity.getType() && ChartCategoryTypeEnum.DASHBOARD.getCode() != entity.getType()) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224037);
        }
        //分组下面有子分类也不能删除
        ChartCategoryQueryPojo chartCategoryQueryPojo = new ChartCategoryQueryPojo();
        //为chartCategorySearchDto赋值corpid等基础信息
        BeanUtil.copyProperties(chartCategoryDeleteDTO, chartCategoryQueryPojo);
        //所有分类类型
        List<Integer> typeIn = ChartCategoryTypeEnum.getCodeList4All();
        chartCategoryQueryPojo.setTypeIn(typeIn);
        //获取以该分类作为父分类的分类列表
        Set<Long> parentIdIn = new HashSet<>();
        parentIdIn.add(id);
        chartCategoryQueryPojo.setParentIdIn(parentIdIn);
        List<ChartCategoryEntity> subList = getChartCategoryList(chartCategoryQueryPojo);
        if (subList.size() > 0) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224038);
        }
        //该分类下无子分类，则再判断该分组下是否有图表，如有图表则也不能删除分类
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("categoryId", id);
        int count = chartModel.getEntitysCount(param);
        count += chartCustomModel.getEntitysCount(param);
        if (count > 0) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224039);
        }
        entity.setDel(1);
        entity.setUpdateTime((long)DateUtil.getInt());
        //只有二级分类需要处理首页发布仪表盘逻辑
        if (!Objects.equals(entity.getParentId(), 0L)) {
            Locale locale = LocaleContextHolder.getLocale();
            String lang = locale.toString();
            HomePageDeleteDTO homePageDeleteDTO = new HomePageDeleteDTO();
            BeanUtil.copyProperties(chartCategoryDeleteDTO, homePageDeleteDTO);
            homePageDeleteDTO.setCategoryId(id);
            try {
                paasFormFeignClient.homePageDelete(homePageDeleteDTO, lang);
            } catch (Exception e) {
                LOG.error("同步删除首页发布信息失败", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }
        chartCategoryModel.update(entity);
        ChartCategoryDeleteVO chartCategoryDeleteVO = new ChartCategoryDeleteVO();
        BeanUtil.copyProperties(entity, chartCategoryDeleteVO, true);

        String userName = chartCategoryDeleteDTO.getLoginUserName();
        // 记录日志
        String logMemoUpdateTemplate = I18nMessageUtil.getMessage(LogMemoConstant.CHART_LOG_MEMO_USER_DELETE_MENU);
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
        String memo = String.format(logMemoUpdateTemplate, userName ,entity.getName());
        mongoLogHelp.buildLog(corpid, chartCategoryDeleteDTO.getUserId(), userName, OperateModuleTypeEnum.CHART_CATEGORY, operateTypeEnum, chartCategoryDeleteDTO.getId().toString(), entity.getName(), memo, chartCategoryDeleteDTO.getHttpHeader());
        return chartCategoryDeleteVO;
    }

    @Override
    public ChartCategoryEnableVO chartCategoryEnable(ChartCategoryEnableDTO chartCategoryEnableDTO) throws XbbException {
        String corpid = chartCategoryEnableDTO.getCorpid();
        Long id = chartCategoryEnableDTO.getId();
        Integer enable = chartCategoryEnableDTO.getEnable();
        ChartCategoryEntity entity = chartCategoryModel.getByKey(id, corpid);
        if (entity == null || entity.getDel() == 1) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224034);
        }
        //（1）当parentId != 0 并且 categoryType=4时，有开启关闭按钮、可改名称、可拖动排序
        //（2）其他情况都是有编辑，可拖动排序，删除（系统分类不能删除）
        if (entity.getParentId().equals(0L)) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224040);
        }
        if (ChartCategoryTypeEnum.CHART_CENTER_CUSTOM.getCode() == entity.getType()) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224041);
        }
        // 记录日志
        String memo;
        OperateTypeEnum operateType;
        String userName = chartCategoryEnableDTO.getLoginUserName();
        if (Objects.equals(BasicConstant.ONE, enable)) {
            if (entity.getEnable().equals(enable)) {
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224042);
            }
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.CHART_LOG_MEMO_USER_UPDATE_MENU_ENABLE), userName, entity.getName());
            operateType = OperateTypeEnum.ENABLE;
        } else {
            if (entity.getEnable().equals(enable)) {
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224043);
            }
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.CHART_LOG_MEMO_USER_UPDATE_MENU_CLOSE), userName, entity.getName());
            operateType = OperateTypeEnum.CLOSE;
        }
        long now = DateUtil.getInt();
        entity.setEnable(enable);
        entity.setUpdateTime(now);
        //name和nameEn的值交换,烦死了
        commonHelp.exchangeChartNameAndNameEn(entity);
        chartCategoryModel.update(entity);

        //获取该分类下的所有图表
        List<ChartEntity> chartList = chartModel.getChartListByCategoryId(corpid, id);
        for (ChartEntity chartEntity : chartList) {
            chartEntity.setEnable(enable);
            chartEntity.setUpdateTime(now);
            //这里name和nameEn的值交换
            commonHelp.exchangeChartNameAndNameEn(chartEntity);
            chartModel.update(chartEntity);
        }

        // 目标管理两边状态按钮要一致
        if (Objects.equals(entity.getType(),ChartCategoryTypeEnum.PERFORMANCE_CUSTOM.getCode())){
            List<ChartEntity> chartCustomList = chartCustomModel.getChartListByCategoryId(corpid, id);
            for (ChartEntity chartEntity : chartCustomList) {
                chartEntity.setEnable(enable);
                chartEntity.setUpdateTime(now);
                //这里name和nameEn的值交换
                commonHelp.exchangeChartNameAndNameEn(chartEntity);
                chartCustomModel.update(chartEntity);
            }
        }

        mongoLogHelp.buildLog(corpid, chartCategoryEnableDTO.getUserId(), userName, OperateModuleTypeEnum.CHART_CATEGORY, operateType, id.toString(), entity.getName(), memo, chartCategoryEnableDTO.getHttpHeader());
        ChartCategoryEnableVO chartCategoryEnableVO = new ChartCategoryEnableVO();
        BeanUtil.copyProperties(entity, chartCategoryEnableVO);
        return chartCategoryEnableVO;
    }

    @Override
    public ChartCategorySortVO chartCategorySort(ChartCategorySortDTO chartCategorySortDTO) throws XbbException {
        List<ChartCategorySortInfoDTO> sortInfo = chartCategorySortDTO.getSortInfo();

        // TODO: 2019/1/16  一级分类不能变为二级，二级分类不能变为一级验证暂时不做

        //分类id---SortInfoDTO（parentId、sort值）
        Map<Long, ChartCategorySortInfoDTO> cidSortInfoDtoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //分类id合集
        Set<Long> categoryIdIn = new HashSet<>();
        categoryIdIn.add(-1L);
        //参数检查，及为获取分类封装参数
        for (ChartCategorySortInfoDTO chartCategorySortInfoDTO: sortInfo) {
            Long id = chartCategorySortInfoDTO.getId();
            //检查排序参数
            checkSortInfo(categoryIdIn, chartCategorySortInfoDTO);
            categoryIdIn.add(id);
            cidSortInfoDtoMap.put(id, chartCategorySortInfoDTO);
            //处理子分类
            List<ChartCategorySortInfoDTO> childList = chartCategorySortInfoDTO.getChildList();
            if (childList != null && childList.size() > 0) {
                for (ChartCategorySortInfoDTO child : childList) {
                    Long childId = child.getId();
                    //检查排序参数
                    checkSortInfo(categoryIdIn, child);
                    categoryIdIn.add(childId);
                    cidSortInfoDtoMap.put(childId, child);
                }
            }
        }
        //查库：把所有的categoryIdIn对应的图表中心分类实体都查出
        List<Integer> typeIn = ChartCategoryTypeEnum.getCodeList4WebChartCenter();
        ChartCategoryQueryPojo chartCategoryQueryPojo = new ChartCategoryQueryPojo();
        //为chartCategorySearchDto赋值corpid等基础信息
        BeanUtil.copyProperties(chartCategorySortDTO, chartCategoryQueryPojo);
        chartCategoryQueryPojo.setTypeIn(typeIn);
        chartCategoryQueryPojo.setIdIn(categoryIdIn);
        List<ChartCategoryEntity> list = getChartCategoryList(chartCategoryQueryPojo);
        long now = DateUtil.getInt();
        for (ChartCategoryEntity entity : list) {
            Long categoryId = entity.getId();
            Long oldParentId = entity.getParentId();
            //用户设置的信息
            ChartCategorySortInfoDTO chartCategorySortInfoDTO = cidSortInfoDtoMap.get(categoryId);
            Long parentId = chartCategorySortInfoDTO.getParentId();
            Integer sort = chartCategorySortInfoDTO.getSort();
            //一二级分类检查
            checkParentId(parentId, oldParentId);
            entity.setParentId(parentId);
            entity.setSort(sort);
            entity.setUpdateTime(now);
            //name和nameEn的值交换
            commonHelp.exchangeChartNameAndNameEn(entity);
            chartCategoryModel.update(entity);
        }
        ChartCategorySortVO chartCategorySortVO = new ChartCategorySortVO();
        return chartCategorySortVO;
    }

    @Override
    public List<ChartCategoryListVO> chartMobileCategoryList(ChartMobileCategoryListDTO chartMobileCategoryListDTO) throws XbbException {
        ChartCategoryListDTO chartCategoryListDTO = new ChartCategoryListDTO();
        BeanUtil.copyProperties(chartMobileCategoryListDTO, chartCategoryListDTO);
        ChartCategoryListVO chartCategoryListVO = chartCategoryList(chartCategoryListDTO);
        List<ChartCategoryListVO> chartMobileCategoryList = chartCategoryListVO.getChildList();
        /*
          把收藏图表置入第一个
          但是要做一个判断：如果没有收藏的图表，则没有该栏目
         */
        Map<String, Object> map = BeanUtil.convertBean2Map(chartMobileCategoryListDTO, true);
        map.put("userId", chartMobileCategoryListDTO.getUserId());
        List<ChartFavoriteEntity> favoriteList = chartFavoriteModel.findEntitys(map);
        Set<Long> chartIdIn = new HashSet<>();
        Set<Long> chartCustomIdIn = new HashSet<>();
        for (ChartFavoriteEntity favoriteEntity : favoriteList) {
            if (Objects.equals(favoriteEntity.getStatisticsType(), StatisticsTypeEnum.CUSTOM_STATISTIC.getCode())) {
                chartCustomIdIn.add(favoriteEntity.getChartId());
            } else {
                chartIdIn.add(favoriteEntity.getChartId());
            }
        }
        Integer count = 0;
        if (chartIdIn.size() > 0) {
            map.put("idIn", chartIdIn);
            count = chartModel.getEntitysCount(map);
        }
        if (chartCustomIdIn.size() > 0) {
            map.put("idIn", chartCustomIdIn);
            count += chartCustomModel.getEntitysCount(map);
        }
        if (count > 0) {
            ChartCategoryListVO top = new ChartCategoryListVO();
            top.setId(CategoryEnum.CATEGORY_FAVORITE.getCode());
            top.setName(CategoryEnum.CATEGORY_FAVORITE.getName());
            top.setType(CategoryEnum.CATEGORY_FAVORITE.getType());
            chartMobileCategoryList.add(0, top);
        }
        return chartMobileCategoryList;
    }

    /**
     * 报表分类初始化
     *
     * @param chartCategoryInitDTO 入参
     * @return com.xbongbong.pro.statistic.pojo.vo.ChartCategoryInitVO
     * @throws XbbException 父类异常
     * @author 徐俊杰
     * @date 2019/1/23 15:23
     */
    @Override
    public ChartCategoryInitVO chartCategoryInit(ChartCategoryInitDTO chartCategoryInitDTO) throws XbbException {
        return chartInitHelp.chartCategoryInit(chartCategoryInitDTO);
    }

    /**
     * 分类和图表初始化，并且获取分类和图表的列表
     *
     * @param chartCategoryInitDTO 入参（包含corpid）
     * @return com.xbongbong.pro.statistic.pojo.vo.ChartInitVO
     * @throws XbbException 初始化图表异常
     * @author 徐俊杰
     * @date 2019/4/3 11:33
     * @since v1.0
     */
    @Override
    public ChartCategoryInitVO categoryAndChartInit(ChartCategoryInitDTO chartCategoryInitDTO) throws XbbException {
        ChartInitDTO chartInitDTO = new ChartInitDTO();
        BeanUtil.copyProperties(chartCategoryInitDTO, chartInitDTO);
        //分类初始化
        chartInitHelp.chartCategoryInit(chartCategoryInitDTO);
        //图表初始化
        chartInitHelp.chartInit(chartInitDTO);
        return chartInitHelp.categoryAndChartList(chartInitDTO);
    }

    @Override
    public ChartCategoryInitVO getIndexCategoryAndChart(ChartCategoryInitDTO chartCategoryInitDTO) throws XbbException {
        return chartInitHelp.getIndexChartCategory(chartCategoryInitDTO);
    }

    /**
     * 呼叫中心的一级分类及二级分类
     *
     * @param baseDTO 入参(corpid)
     * @return com.xbongbong.pro.statistic.pojo.vo.ChartCategoryListVO
     * @author 徐俊杰
     * @date 2019/6/24 16:04
     * @since v1.0
     */
    @Override
    public ChartCategoryListVO callCenterLink(BaseDTO baseDTO) {
        //查询图表分类
        //包装入参
        ChartCategoryQueryPojo chartCategoryQueryPojo = new ChartCategoryQueryPojo();
        chartCategoryQueryPojo.setEnable(BasicConstant.IS_USE);
        chartCategoryQueryPojo.setCorpid(baseDTO.getCorpid());
        List<Integer> typeIn = new ArrayList<>();
        typeIn.add(ChartCategoryTypeEnum.CALL_CENTER.getCode());
        chartCategoryQueryPojo.setTypeIn(typeIn);
        List<ChartCategoryEntity> categoryEntities = getChartCategoryList(chartCategoryQueryPojo);
        ChartCategoryListVO father = new ChartCategoryListVO();
        List<ChartCategoryListVO> childList = new ArrayList<>();
        for (ChartCategoryEntity entity : categoryEntities) {
            Long parentId = entity.getParentId();
            if (Objects.equals(ChartConstant.PARENT_CATEGORY, parentId)) {
                //处理父分类
                father.setId(entity.getId());
            } else {
                //处理子分类
                ChartCategoryListVO child = new ChartCategoryListVO();
                child.setId(entity.getId());
                childList.add(child);
            }
        }
        father.setChildList(childList);
        return father;
    }

    @Override
    public CategorySearchVO categorySearchSaveBatch(CategorySearchSaveDTO categorySearchSaveDTO) throws XbbException {
        CategorySearchVO categorySearchVO = new CategorySearchVO();
        Long categoryId = categorySearchSaveDTO.getCategoryId();
        List<ChartCategorySearchEntity> searchList = categorySearchSaveDTO.getSearchList();
        Integer size = chartCategorySearchModel.getCountsByCategoryId(categoryId, categorySearchSaveDTO.getCorpid());
        if ((size + searchList.size()) > ChartConstant.SEARCH_SIZE_MAX) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224069, StatisticsServicesErrorCodeEnum.API_ERROR_224069.getMsg(), ChartConstant.SEARCH_SIZE_MAX);
        }
        searchList.removeIf(next -> Objects.isNull(next.getFieldType()));
        searchList.forEach(chartCategorySearchEntity -> {
            chartCategorySearchEntity.setCorpid(categorySearchSaveDTO.getCorpid());
            chartCategorySearchEntity.setCreatorId(categorySearchSaveDTO.getUserId());
            chartCategorySearchEntity.setCategoryId(categoryId);
            //是否全局
            if (Objects.equals(chartCategorySearchEntity.getGlobal(), ChartConstant.IS_GLOBAL)){
                chartCategorySearchEntity.setGlobal(ChartConstant.IS_GLOBAL);
            }
        });
        try {
            chartCategorySearchModel.insertBatch(searchList);
        } catch (Exception e) {
            LOG.error("categorySearchSaveBatch 批量新增失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return categorySearchVO;
    }

    @Override
    public CategorySearchVO categorySearchUpdateBatch(CategorySearchSaveBatchDTO categorySearchSaveBatchDTO) throws XbbException {
        CategorySearchVO categorySearchVO = new CategorySearchVO();
        String corpid = categorySearchSaveBatchDTO.getCorpid();
        List<ChartCategorySearchEntity> chartCategorySearchList = categorySearchSaveBatchDTO.getSearchList();
        Set<Long> idSet = new HashSet<>();
        for (ChartCategorySearchEntity chartCategorySearchEntity : chartCategorySearchList) {
            if(Objects.equals(chartCategorySearchEntity.getDel(),0)){
                idSet.add(chartCategorySearchEntity.getId());
            }
        }
        //更新的时候传进来del=0的数量大于限制则返回提示
        if (idSet.size() > ChartConstant.SEARCH_SIZE_MAX) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224069, StatisticsServicesErrorCodeEnum.API_ERROR_224069.getMsg(), ChartConstant.SEARCH_SIZE_MAX);
        }
        try {
            chartCategorySearchModel.updateBatch(chartCategorySearchList, corpid);
        } catch (Exception e) {
            LOG.error("categorySearchUpdateBatch 批量更新失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return categorySearchVO;
    }

    @Override
    public CategoryTextGetVO categoryTextGet(CategoryTextGetDTO categoryTextGetDTO) throws XbbException {
        Long textId = categoryTextGetDTO.getCategoryTextId();
        ChartCategoryTextEntity categoryTextEntity = chartCategoryTextModel.getById(textId, categoryTextGetDTO.getCorpid());
        if (categoryTextEntity == null) {
            throw new XbbException(ImportErrorCodeEnum.API_ERROR_235012, ImportErrorCodeEnum.API_ERROR_235012.getMsg(), "文本组件");
        }
        CategoryTextGetVO categoryTextGetVO = new CategoryTextGetVO();
        categoryTextGetVO.setTextEntity(categoryTextEntity);
        return categoryTextGetVO;
    }

    @Override
    public CategoryTextGetListVO categoryTextGetList(CategoryTextGetListDTO categoryTextGetListDTO) throws XbbException {
        Long categoryId = categoryTextGetListDTO.getCategoryId();
        List<ChartCategoryTextEntity> searchList = chartCategoryTextModel.getByCategoryId(categoryId, categoryTextGetListDTO.getCorpid());
        CategoryTextGetListVO categoryTextGetListVO = new CategoryTextGetListVO();
        categoryTextGetListVO.setTextList(searchList);
        return categoryTextGetListVO;
    }


    @Override
    public CategorySearchGetVO categorySearchGet(CategorySearchGetDTO categorySearchGetDTO) throws XbbException {
        Long searchId = categorySearchGetDTO.getCategorySearchId();
        ChartCategorySearchEntity categorySearchEntity = chartCategorySearchModel.getById(searchId, categorySearchGetDTO.getCorpid());
        if (categorySearchEntity == null) {
            throw new XbbException(ImportErrorCodeEnum.API_ERROR_235012, ImportErrorCodeEnum.API_ERROR_235012.getMsg(), "查询条件");
        }
        CategorySearchGetVO categorySearchGetVO = new CategorySearchGetVO();
        categorySearchGetVO.setSearchEntity(categorySearchEntity);
        return categorySearchGetVO;
    }

    @Override
    public CategorySearchGetListVO categorySearchGetList(CategorySearchGetListDTO categorySearchGetListDTO) throws XbbException {
        Long categoryId = categorySearchGetListDTO.getCategoryId();
        List<ChartCategorySearchEntity> searchList = chartCategorySearchModel.getByCategoryId(categoryId, categorySearchGetListDTO.getCorpid());
        CategorySearchGetListVO categorySearchGetListVO = new CategorySearchGetListVO();
        categorySearchGetListVO.setSearchList(searchList);
        return categorySearchGetListVO;
    }

    @Override
    public CategoryTextVO categoryTextSaveBatch(CategoryTextSaveDTO categoryTextSaveDTO) throws XbbException {
        CategoryTextVO categoryTextVO = new CategoryTextVO();
        Long categoryId = categoryTextSaveDTO.getCategoryId();
        List<ChartCategoryTextEntity> textList = categoryTextSaveDTO.getTextList();
        List<ChartCategoryTextEntity> insertList = new ArrayList<>();
        List<ChartCategoryTextEntity> updateList = new ArrayList<>();
        // 文本组件限制
        chartCategoryTextService.limit(categoryTextSaveDTO.getCorpid(),categoryId,textList);
        textList.forEach(chartCategoryTextEntity -> {
            chartCategoryTextEntity.setCorpid(categoryTextSaveDTO.getCorpid());
            chartCategoryTextEntity.setCreatorId(categoryTextSaveDTO.getUserId());
            chartCategoryTextEntity.setCategoryId(categoryId);
            if (null == chartCategoryTextEntity.getId()){
                insertList.add(chartCategoryTextEntity);
            }else {
                updateList.add(chartCategoryTextEntity);
            }
        });
        try {
            if (CollectionUtils.isNotEmpty(insertList)){
                chartCategoryTextModel.insertBatch(insertList);
            }
            if (CollectionUtils.isNotEmpty(updateList)){
                chartCategoryTextModel.updateBatch(updateList,categoryTextSaveDTO.getCorpid());
            }
        } catch (Exception e) {
            LOG.error("categoryTextSaveBatch 批量新增失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return categoryTextVO;
    }

    @Override
    public CategorySearchVO categoryPermissionUpdate(CategoryPermissionSaveDTO categoryPermissionSaveDTO) throws XbbException {
        CategorySearchVO categorySearchVO = new CategorySearchVO();
        Long categoryId = categoryPermissionSaveDTO.getCategoryId();
        JSONObject permissions = categoryPermissionSaveDTO.getPermissions();
        if (permissions != null) {
            ChartCategoryEntity chartCategoryEntity = new ChartCategoryEntity();
            chartCategoryEntity.setId(categoryId);
            chartCategoryEntity.setPermissions(permissions);
            chartCategoryEntity.setCorpid(categoryPermissionSaveDTO.getCorpid());
            try {
                chartCategoryModel.update(chartCategoryEntity);
            } catch (Exception e) {
                LOG.error("categoryPermissionUpdate 更新失败", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }
        return categorySearchVO;
    }

    @Override
    public CategoryFieldGetVO categoryFieldGet(CategoryFieldGetDTO categoryFieldGetDTO) throws XbbException {
        CategoryFieldGetVO categoryFieldGetVO = new CategoryFieldGetVO();
        Long categoryId = categoryFieldGetDTO.getCategoryId();
        List<Integer> fieldTypeList = categoryFieldGetDTO.getFieldTypeList();
        JSONArray chartFields = new JSONArray();
        String corpid = categoryFieldGetDTO.getCorpid();
        //只有自定义图表请求该接口
        Map<String, Object> params = new HashMap<>(1 << 4);
        params.put("corpid", corpid);
        params.put("del", DelEnum.NORMAL.getDel());
        params.put("categoryId", categoryId);
        List<ChartEntity> list = chartCustomModel.findEntitys(params);
        Set<Long> formIds = new HashSet<>();
        Set<Long> workOrderFormIds = new HashSet<>();
        List<PaasFormExplainEntity> paasFormExplainEntities = new ArrayList<>();
        Map<Long, Map<String, FieldAttrEntity>> paasFormExplainMap = new HashMap<>();
        List<WorkOrderExplainEntity> workOrderExplainEntities = new ArrayList<>();
        Map<Long, Map<String, FieldAttrEntity>> workOrderFormExplainMap = new HashMap<>();
        for (ChartEntity chartEntity : list) {
            JSONArray displayAttr = chartEntity.getDisplayAttr();
            JSONArray rowGroupAttr = chartEntity.getRowGroupAttr();
            JSONArray colGroupAttr = chartEntity.getColGroupAttr();
            JSONArray chartClassify = chartEntity.getChartClassify();
            JSONArray chartSeries = chartEntity.getChartSeries();
            JSONObject belongAttr = chartEntity.getBelongAttr();
            JSONObject timeAttr = chartEntity.getTimeAttr();
            JSONArray summaryAttr = chartEntity.getSummaryAttr();
            JSONArray penetrateAttr = chartEntity.getPenetrateAttr();
            //自定义pk的直接跳过
            if(Objects.equals(chartEntity.getChartType(),ChartTypeEnum.PK_CUSTOM.getCode())){
                continue;
            }
            Map<Long, DataSourceObjectVO> formIdToDataSource = new HashMap<>(1 << 4);
            JSONObject driveSource = chartEntity.getDriverSources();
            List<DataSourceObjectVO> dataList = new ArrayList<>();
            DataSourceObjectVO dataSource = new DataSourceObjectVO();
            dataSource.setName(driveSource.getString("name"));
            Long driveFormId = driveSource.getLong("formId");
            dataSource.setFormId(driveFormId);
            dataList.add(dataSource);
            if(Objects.isNull(driveFormId)){
                /**
                 * @Description 数据集仪表盘筛选条件选择处理
                 *
                 **/
                ArrayList<JSONArray> jsonArray = Lists.newArrayList(displayAttr, rowGroupAttr, colGroupAttr, chartClassify, chartSeries, summaryAttr, penetrateAttr);
                jsonArray.stream().forEach(array->putFormIdToDataSource(formIdToDataSource, dataSource, array));
                putJsonObjFormIdToDataSouce(formIdToDataSource, dataSource, belongAttr);
                putJsonObjFormIdToDataSouce(formIdToDataSource, dataSource, timeAttr);
            }else {
                formIdToDataSource.put(driveFormId, dataSource);
            }

            if (Objects.equals(driveSource.getInteger("businessType"), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                workOrderFormIds.add(driveFormId);
            } else {
                formIds.add(driveFormId);
            }
            JSONArray slaveSources = chartEntity.getSlaveSources();
            if (slaveSources != null && slaveSources.size() > 0) {
                for (int i = 0; i < slaveSources.size() ; i++) {
                    JSONObject jsonObject = slaveSources.getJSONObject(i);
                    DataSourceObjectVO dataSourceObjectVO = new DataSourceObjectVO();
                    dataSourceObjectVO.setName(jsonObject.getString("name"));
                    Long formId = jsonObject.getLong("formId");
                    dataSourceObjectVO.setFormId(formId);
                    formIdToDataSource.put(formId, dataSourceObjectVO);
                    dataList.add(dataSourceObjectVO);
                    formIds.add(formId);
                }
            }
            if(Objects.nonNull(driveFormId)) {
                paasFormExplainEntities = paasFormExplainModel.getByFormIdIn(formIds, corpid);
                paasFormExplainEntities.forEach(v -> paasFormExplainMap.put(v.getFormId(), ExplainUtil.getExplainMap(v.getExplains())));
                workOrderExplainEntities = workOrderExplainModel.getByFormIdIn(workOrderFormIds, corpid);
                workOrderExplainEntities.forEach(v -> workOrderFormExplainMap.put(v.getFormId(), ExplainUtil.getExplainMap(v.getExplains())));
            }
            JSONObject chartField = new JSONObject();
            Long chartId = chartEntity.getId();
            chartField.put("id", chartId);
            chartField.put("chartName", chartEntity.getName());
            chartField.put("chartType", chartEntity.getChartType());
            chartField.put("single",chartEntity.getSingle());
            if(Objects.isNull(driveFormId)){
                chartField.put("dataSetId",driveSource.getLong("dataSetId"));
            }
            getFieldAttrsByType(displayAttr, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
            getFieldAttrsByType(rowGroupAttr, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
            getFieldAttrsByType(colGroupAttr, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
            getFieldAttrsByType(chartClassify, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
            getFieldAttrsByType(chartSeries, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
            getFieldAttrsByType(summaryAttr, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
            getFieldAttrByType(belongAttr, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
            getFieldAttrByType(timeAttr, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
            getFieldAttrsByType(penetrateAttr, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
            dataList.removeIf(e -> CollectionsUtil.isEmpty(e.getFieldList()));
            if (CollectionsUtil.isNotEmpty(dataList)) {
                //处理指标图客户，机会筛选条件多出一条问题 bug_id 52565
                if (dataListIsRepeat(dataList)){
                    handleDataList(dataList);
                }
                chartField.put("sources", dataList);
                chartFields.add(chartField);
            }

            formIds.clear();
            workOrderFormIds.clear();
            paasFormExplainMap.clear();
            workOrderFormExplainMap.clear();
        }
        categoryFieldGetVO.setChartFields(chartFields);
        return categoryFieldGetVO;
    }
    /**
     * @author  gzt
     * @Description formId 循环添加到formIdToDataSource中
     * @Date 11:14 2022/10/14
     * @param formIdToDataSource
     * @param dataSource
     * @param timeAttr
     * @throws
     **/

    private void putJsonObjFormIdToDataSouce(Map<Long, DataSourceObjectVO> formIdToDataSource, DataSourceObjectVO dataSource, JSONObject timeAttr) {
        if (timeAttr != null) {
            ChartFieldAttrPojo chartFieldAttrPojo = JSON.parseObject(timeAttr.toJSONString(), ChartFieldAttrPojo.class);
            formIdToDataSource.putIfAbsent(chartFieldAttrPojo.getFormId(), dataSource);
        }
    }

    /**
     * @author  gzt
     * @Description formId 循环添加到formIdToDataSource中
     * @Date 11:14 2022/10/14
     * @param formIdToDataSource
     * @param dataSource
     * @param penetrateAttr
     * @throws
     **/
    private void putFormIdToDataSource(Map<Long, DataSourceObjectVO> formIdToDataSource, DataSourceObjectVO dataSource, JSONArray penetrateAttr) {
        for (int i = 0; i < penetrateAttr.size(); i++) {
            JSONObject obj = penetrateAttr.getJSONObject(i);
            ChartFieldAttrPojo chartFieldAttrPojo = JSON.parseObject(obj.toJSONString(), ChartFieldAttrPojo.class);
            formIdToDataSource.putIfAbsent(chartFieldAttrPojo.getFormId(), dataSource);
        }
    }

    public boolean dataListIsRepeat(List<DataSourceObjectVO> dataList){
        for (DataSourceObjectVO dataSourceObjectVO : dataList) {
            List<String> list = new ArrayList<>(1<<4);
            String attrName ;
            if (dataSourceObjectVO != null){
                List<? super FieldAttrEntity> fieldList = dataSourceObjectVO.getFieldList();
                if (CollectionsUtil.isNotEmpty(fieldList)){
                    for (Object o : fieldList) {
                        FieldAttrEntity fieldAttrEntity = (FieldAttrEntity) o;
                        if (fieldAttrEntity != null) {
                            attrName = fieldAttrEntity.getAttrName();
                            if (attrName != null){
                                list.add(attrName);
                            }
                        }
                    }
                    if (CollectionsUtil.isNotEmpty(list)){
                        HashSet<String> set = new HashSet<>(list);
                        if (set.size() < list.size()){
                                return true;
                        }
                    }
                }
            }
        }
        return false;
    }
    public void handleDataList(List<DataSourceObjectVO> dataList){

        for (DataSourceObjectVO dataSourceObjectVO : dataList) {
            String attr;
            if (dataSourceObjectVO != null){
                List<? super FieldAttrEntity> fieldList = dataSourceObjectVO.getFieldList();
                if (CollectionsUtil.isNotEmpty(fieldList)){
                    Iterator<? super FieldAttrEntity> iterator = fieldList.iterator();
                    while (iterator.hasNext()){
                        FieldAttrEntity fieldAttrEntity = (FieldAttrEntity) iterator.next();
                        if (fieldAttrEntity != null){
                            if (fieldAttrEntity.getOriginalAttr() == null){
                                attr = fieldAttrEntity.getAttr();
                                iterator.remove();
                                Set<String> fieldAttrList = dataSourceObjectVO.getFieldAttrList();
                                Iterator<String> iterator1 = fieldAttrList.iterator();
                                while (iterator1.hasNext()){
                                    String next = iterator1.next();
                                    if (attr != null){
                                        if (next.equals(attr)){
                                            iterator1.remove();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public CategorySearchVO categoryPublish(CategoryPublishDTO categoryPublishDTO) throws XbbException {
        String corpid = categoryPublishDTO.getCorpid();
        Long categoryId = categoryPublishDTO.getCategoryId();
        Integer publish = categoryPublishDTO.getPublish();
        Map<String, Object> param = new HashMap<>(1 << 4);
        param.put(StringConstant.CORPID, corpid);
        param.put("configAlias", UserConfigEnum.HOME_MANAGEMENT.getAlias());
        List<UserConfigEntity> userConfigEntities = userConfigModel.list(param);
        if (!Objects.equals(categoryPublishDTO.getIsCustom(),BasicConstant.ONE)){
            ChartCategoryEntity chartCategoryEntity = chartCategoryModel.getByKey(categoryId,corpid);
            if (null == chartCategoryEntity || chartCategoryEntity.getDel() == 1) {
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224084, StatisticsServicesErrorCodeEnum.API_ERROR_224084.getMsg());
            }
            if (Objects.equals(chartCategoryEntity.getPublish(),publish)){
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224085, StatisticsServicesErrorCodeEnum.API_ERROR_224085.getMsg());
            }
        }
        CompanyConfigEntity configEntity = companyConfigModel.getConfigEntity(corpid, UserConfigEnum.HOME_MANAGEMENT.getAlias());
        JSONArray companyConfigValueArr = null;
        if (configEntity != null) {
            companyConfigValueArr = JSON.parseArray(configEntity.getConfigValue());
        }
        JSONArray companyConfigValueAttrTemp = new JSONArray();
        JSONArray companyConfigValueAttrCustom = new JSONArray();
        if (CollectionUtils.isNotEmpty(companyConfigValueArr)){
            companyConfigValueArr.forEach(item ->{
                JSONObject jsonObject = (JSONObject) item;
                if (Objects.equals(jsonObject.getInteger(HomePageCustomTypeEnum.IS_CUSTOM.getAlias()),HomePageCustomTypeEnum.IS_CUSTOM.getCode())){
                    companyConfigValueAttrCustom.add(item);
                }else {
                    companyConfigValueAttrTemp.add(item);
                }
            });
        }
        if (Objects.equals(publish, ChartPublishEnum.PUBLISH.getCode())) {
            if (Objects.equals(categoryPublishDTO.getIsCustom(),1)){
                if (companyConfigValueAttrCustom != null && companyConfigValueAttrCustom.size() >= ChartConstant.PUBLISH_MAX) {
                    throw new XbbException(BiErrorCodeEnum.API_ERROR_241016);
                }
            }else {
                if (companyConfigValueAttrTemp != null && companyConfigValueAttrTemp.size() >= ChartConstant.PUBLISH_MAX) {
                    throw new XbbException(BiErrorCodeEnum.API_ERROR_241016);
                }
            }
        }
        for (UserConfigEntity userConfigEntity : userConfigEntities) {
            if (userConfigEntity == null) {
                continue;
            }
            JSONArray userConfigValueArr = JSON.parseArray(userConfigEntity.getConfigValue());
            if (userConfigValueArr != null && userConfigValueArr.size() > 0) {
                String configValue = getConfigValueByPublish(userConfigValueArr, categoryPublishDTO);
                userConfigEntity.setConfigValue(configValue);
            }
        }
        if (CollectionsUtil.isNotEmpty(userConfigEntities)) {
            userConfigModel.updateBatch(userConfigEntities, corpid);
        }
        String configValue;
        if (companyConfigValueArr == null || companyConfigValueArr.size() == 0) {
            companyConfigValueArr = new JSONArray();
            //兼容没有首页管理公司配置的情况
            HomePagePoJo homePagePoJo = new HomePagePoJo(0L, "CRM首页", 0, 1);
            companyConfigValueArr.add(homePagePoJo);
        }
        configValue = getConfigValueByPublish(companyConfigValueArr, categoryPublishDTO);
        try {
            companyConfigModel.save(corpid, UserConfigEnum.HOME_MANAGEMENT.getAlias(), UserConfigEnum.HOME_MANAGEMENT.getName(), configValue);
        } catch (Exception e) {
            LOG.error("categoryPublish companyConfigModel.save", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        try {
            chartCategoryModel.updatePublishFlag(categoryId, publish, corpid);
        } catch (Exception e) {
            LOG.error("categoryPublish updatePublishFlag", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return new CategorySearchVO();
    }

    @Override
    public CategorySearchVO categoryUpgrade(CategoryUpgradeDTO categoryUpgradeDTO) throws XbbException {
        List<Long> categoryIdIn = categoryUpgradeDTO.getCategoryIdIn();
        String corpid = categoryUpgradeDTO.getCorpid();
        List<ChartCategoryEntity> list = new ArrayList<>();
        categoryIdIn.forEach(e -> {
            ChartCategoryEntity chartCategoryEntity = new ChartCategoryEntity();
            chartCategoryEntity.setId(e);
            chartCategoryEntity.setType(ChartCategoryTypeEnum.DASHBOARD.getCode());
            chartCategoryEntity.setPermissions(JSON.parseObject(PERMISSION_OTHER_MSG));
            list.add(chartCategoryEntity);
        });
        if (list.size() > 0) {
            try {
                chartCategoryModel.updateBatch(list, corpid);
            } catch (Exception e) {
                LOG.error("categoryUpgrade chartCategoryModel.updateBatch", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }
        Map<String, Object> param = new HashMap<>(1 << 4);
        param.put("categoryIdIn", categoryIdIn);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(StringConstant.CORPID, corpid);
        param.put("columns", "id");
        List<ChartEntity> chartEntityList = chartCustomModel.findEntitys(param);
        chartEntityList.forEach(e -> e.setSearch(new JSONArray()));
        if (chartEntityList.size() > 0) {
            try {
                chartCustomModel.updateBatch(chartEntityList, corpid);
            } catch (Exception e) {
                LOG.error("categoryUpgrade chartModel.updateBatch", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }
        return new CategorySearchVO();
    }

    @Override
    public ChartCategoryListByIdInVO chartCategoryListByIdIn(ChartCategoryListByIdInDTO chartCategoryListByIdInDTO) throws XbbException {
        ChartCategoryListByIdInVO chartCategoryListByIdInVO = new ChartCategoryListByIdInVO();
        List<ChartCategoryEntity> categoryEntities = getByIdIn(chartCategoryListByIdInDTO.getIdIn(),chartCategoryListByIdInDTO.getCorpid());
        Map<Long, List<Long>> subAllDepIdMap = departmentModel.getSubDepIdMap(chartCategoryListByIdInDTO.getCorpid(), false);
        categoryEntities.removeIf(entity -> {
            Long parentId = entity.getParentId();
            if (!parentId.equals(0L)) {
                JSONObject permissions = entity.getPermissions();
                //权限判断
                return !customHelp.judgeCategoryPermissions(permissions, chartCategoryListByIdInDTO, subAllDepIdMap);
            }
            return false;
        });
        chartCategoryListByIdInVO.setList(categoryEntities);
        return chartCategoryListByIdInVO;
    }

    private List<ChartCategoryEntity> getByIdIn(List<Long> idIn,String corpid){
        Map<String, Object> param = new HashMap<>(1 << 4);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("idIn", idIn);
        List<ChartCategoryEntity> categoryEntities = chartCategoryModel.findEntitys(param);
        categoryEntities = null == categoryEntities ? new ArrayList<>():categoryEntities;
        return categoryEntities;
    }

    /**
     * 检查一级分类和二级分类是否互换：
     * 		一级分类不能变成二级分类；二级分类不能变成一级分类
     * @param parentId 新的父分类id
     * @param oldParentId 旧的父分类id
     * @throws XbbException
     * @author zcp
     * @date 2019/1/16 21:30
     * @since v1.0
     * @version v1.0
     */
    private void checkParentId(Long parentId, Long oldParentId) throws XbbException {
        if (oldParentId.equals(0L) && !parentId.equals(0L)) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224044);
        }
        if (!oldParentId.equals(0L) && parentId.equals(0L)) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224045);
        }
    }

    /**
     * 检查排序信息
     * @param categoryIdIn 分类id
     * @param chartCategorySortInfoDTO 排序信息
     * @throws XbbException
     * @author zcp
     * @date 2019/1/16 21:43
     * @since v1.0
     * @version v1.0
     */
    private void checkSortInfo(Set<Long> categoryIdIn, ChartCategorySortInfoDTO chartCategorySortInfoDTO) throws XbbException {
        Long id = chartCategorySortInfoDTO.getId();
        if (categoryIdIn.contains(id)) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224046);
        }
    }
    /**
     * 获取分类下的图表列表
     * @param chartCategoryListDTO 查询分类列表参数
     * @param supCategoryIdIn 有图表的分类ids（此处指图表中心系统二级分类）
     * @return java.util.Map<java.lang.Long,java.util.List<com.xbongbong.pro.statistic.pojo.vo.ChartBaseInfoVO>>
     * @throws XbbException
     * @author zcp
     * @date 2019/1/21 15:31
     * @since v1.0
     * @version v1.0
     */
    private Map<Long, List<ChartBaseInfoVO>> getSubChart(ChartCategoryListDTO chartCategoryListDTO, Set<Long> supCategoryIdIn) throws XbbException {
        //权限
        UserVO loginUser = chartCategoryListDTO.getLoginUser();
        //获取该员工所在部门及所有下级部门
        Set<Long> depIdIn = chartPermissionHelp.getAllDeptIds(loginUser);
        //saas权限
        Set<String> saasPermissions = loginUser.getPermSet();
        //paas权限
        Map<Long, List<Long>> appMenuMap = chartPermissionHelp.getPaasPermissionMap(loginUser.getPaasPermissions());
        if (supCategoryIdIn == null || supCategoryIdIn.size() == 0) {
           return new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        }
        ChartListDTO chartListDTO = new ChartListDTO();
        BeanUtil.copyProperties(chartCategoryListDTO, chartListDTO, true);
        //塞入map
        Map<String, Object> map = BeanUtil.convertBean2Map(chartListDTO, true);
        map.put("categoryIdIn", supCategoryIdIn);
        map.put("orderByStr", "sort DESC, id ASC");
        map.put("publish", ChartPublishEnum.PUBLISH.getCode());
        map.put(StringConstant.COLUMNS, "id,corpid,category,statistics_type,system_code,enable,chart_type,show_types,publish,name,old_name,name_en,icon,color,permissions,driver_sources,ref_types,unit,sort,explains,join_rule,remove_rule,scope_rule,power_type,item_style_option,chart_classify");
        List<ChartEntity> list = chartModel.findEntitys(map);
        list.addAll(chartCustomModel.findEntitys(map));
        //分类id---该分类下的所有图表列表
        Map<Long, List<ChartBaseInfoVO>> categoryChartsMap = new HashMap<>(list.size());
        for (ChartEntity chartEntity : list) {
            //saas模块权限和paas的app权限过滤
            if (chartPermissionHelp.filterProPermission4Chart(loginUser,chartEntity, saasPermissions, appMenuMap)) {
                continue;
            }
            // 图表具体权限
            if (chartPermissionHelp.filterPermission4SingleChart(loginUser, depIdIn, chartEntity)) {
                continue;
            }
            //判断是否可以发布到首页,不能发布到首页的图无法加入
            if (commonHelp.publishFilter(chartEntity.getSystemCode(), chartEntity.getChartType())) {
                continue;
            }
            List<Long> cidList = chartEntity.getCategory().toJavaList(Long.class);
            for (Long categoryId : cidList) {
                List<ChartBaseInfoVO> chartList = categoryChartsMap.get(categoryId);
                if (chartList == null) {
                    chartList = new ArrayList<>();
                }
                ChartBaseInfoVO chartBaseInfoVO = new ChartBaseInfoVO();
                BeanUtil.copyProperties(chartEntity, chartBaseInfoVO);
                chartBaseInfoVO.setChartCategoryId(chartEntity.getId());
                StatisticsTypeEnum statisticsTypeEnum = StatisticsTypeEnum.getByCode(chartEntity.getStatisticsType());
                chartBaseInfoVO.setStatisticsTypeName(statisticsTypeEnum.getName());
                //图表可拖动
                chartBaseInfoVO.setDrag(1);
                chartBaseInfoVO.setChartType(chartEntity.getChartType());
                chartBaseInfoVO.setSecondCategoryId(chartEntity.getCategoryId());
                chartList.add(chartBaseInfoVO);
                categoryChartsMap.put(categoryId, chartList);
            }
        }
        return categoryChartsMap;
    }

    /**
     * saas模块筛选
     *
     * @param chartCategoryEntity 图表分类
     * @param saasPermissions saas权限
     * @return boolean
     * @author 徐俊杰
     * @date 2019/6/13 11:17
     * @since v1.0
     */
    private boolean permission4saas(ChartCategoryEntity chartCategoryEntity, Set<String> saasPermissions) {
        String alias = chartCategoryEntity.getAlias();
        ChartCategoryAliasEnum aliasEnum = ChartCategoryAliasEnum.getByAlias(alias);
        //alias不存在，异常
        if (aliasEnum == null) {
            return false;
        }
        //不过滤权限的模块，简报看板、业绩目标、PK榜、公告、销售简报
        if (aliasEnum == ChartCategoryAliasEnum.REPORT_BOARD ||
                aliasEnum == ChartCategoryAliasEnum.PERFORMANCE ||
                aliasEnum == ChartCategoryAliasEnum.PK ||
                aliasEnum == ChartCategoryAliasEnum.ANNOUNCEMENT ||
                aliasEnum == ChartCategoryAliasEnum.SALES_REPORT ||
                aliasEnum == ChartCategoryAliasEnum.RAIDERS
        ) {
            return true;
        }

        if(aliasEnum == ChartCategoryAliasEnum.REMIND) {
            return saasPermissions.contains(ProPermissionAliasEnum.CUSTOMER_COMMUNICATE.getAlias()) ||
                    saasPermissions.contains(ProPermissionAliasEnum.SUPPLIER_COMMUNICATE.getAlias());
        } if(aliasEnum == ChartCategoryAliasEnum.DATA_WARNING) {
            try {
                return saasPermissions.contains(ProPermissionAliasEnum.DATA_CENTER.getAlias()) &&
                        Objects.equals(packageHelp.getFeeType(chartCategoryEntity.getCorpid()),PackageTypeEnum.ULTIMATE.getType());
            } catch (XbbException e) {
                e.printStackTrace();
            }
        }else if (aliasEnum.getProPermissionAlias().equals(XbbRefTypeEnum.UNKNOWN.getAlias())) {
            return false;
        }
        //根据模块权限进行过滤
        return saasPermissions.contains(aliasEnum.getProPermissionAlias());
    }

    /**
     * 判断首页右侧看板，攻略卡片是否开启
     *
     * @param chartCategoryEntity 图表分类实体
     * @param corpid 公司id
     * @return boolean
     * @author 徐俊杰
     * @date 2019/10/30 9:41
     * @since v1.0
     */
    private boolean checkRaiders(ChartCategoryEntity chartCategoryEntity, String corpid) {
        String alias = chartCategoryEntity.getAlias();
        if (Objects.equals(alias, ChartCategoryAliasEnum.RAIDERS.getAlias())) {
            String raidersAlias = CompanyConfigEnum.RAIDERS.getAlias();
            //获取攻略的company-config
            CompanyConfigEntity raidersConfig = companyConfigModel.getByConfigAlias(raidersAlias, corpid);
            //查不到则返回false
            if (raidersConfig == null) {
                return false;
            } else {
                // 价值攻略始终展示
                /*String configValue = raidersConfig.getConfigValue();
                //查到如果是开启则返回true
                return Objects.equals(Integer.valueOf(configValue), RaidersConstant.ENABLE);*/
                return true;
            }
        } else {
            //不是价值攻略则返回true
            return true;
        }
    }

    /**
     * 根据fieldType获取可选择字段
     * @param fieldAttr chart中存储字段信息
     * @param fieldTypeList 字段类型
     * @param formIdToDataSource formID对应dataSource对象关系
     * @param paasFormExplainMap
     * @param workOrderFormExplainMap
     * @author zhouwq
     * @date 2020/8/26 16:03
     */
    private static void getFieldAttrsByType(JSONArray fieldAttr, List<Integer> fieldTypeList, Map<Long, DataSourceObjectVO> formIdToDataSource, Long chartId, Map<Long, Map<String, FieldAttrEntity>> paasFormExplainMap, Map<Long, Map<String, FieldAttrEntity>> workOrderFormExplainMap) {
        if (fieldAttr == null) {
            return;
        }
        for (int i = 0; i < fieldAttr.size(); i++) {
            JSONObject obj = fieldAttr.getJSONObject(i);
            ChartFieldAttrPojo chartFieldAttrPojo = JSON.parseObject(obj.toJSONString(), ChartFieldAttrPojo.class);
            Integer screenType = chartFieldAttrPojo.getScreenType();
            if (screenType != null && screenType < ScreenTypeEnum.SCREEN_SEARCH.getType()) {
                continue;
            }
            //合同（产品）单位字段过滤
            if (BIProductEnum.getByCode(chartFieldAttrPojo.getBusinessType()) != null && Objects.equals(chartFieldAttrPojo.getOriginalAttr(), ContractProductBIEnum.UNIT.getAttr())) {
                continue;
            }
            Long formId = chartFieldAttrPojo.getFormId();
            Integer chartFieldType = chartFieldAttrPojo.getFieldType();
            //子表单字段处理
            if (FieldTypeEnum.isSubFormType(chartFieldType)) {
                SubFormPoJo subFormPoJo = chartFieldAttrPojo.getSubForm();
                if (subFormPoJo != null) {
                    String parentSubFormName = chartFieldAttrPojo.getAttrName();
                    String parentSubFormAttr = chartFieldAttrPojo.getAttr();
                    List<ChartFieldAttrPojo> fieldAttrEntities = JSON.parseArray(JSON.toJSONString(subFormPoJo.getItems()), ChartFieldAttrPojo.class);
                    fieldAttrEntities.forEach(e -> {
                        boolean isOpen = true;
                        if (Objects.equals(chartFieldAttrPojo.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                            Map<String, FieldAttrEntity> fieldAttrEntityMap = workOrderFormExplainMap.get(formId);
                            if(fieldAttrEntityMap != null){
                                FieldAttrEntity fieldAttrEntity = fieldAttrEntityMap.get(chartFieldAttrPojo.getAttr());
                                if(fieldAttrEntity != null){
                                    SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                                    List<? extends FieldAttrEntity> items = subForm.getItems();
                                    for (FieldAttrEntity v : items) {
                                        if (Objects.equals(v.getAttr(), e.getAttr()) && Objects.equals(v.getIsOpen(), 2)) {
                                            isOpen = false;
                                            break;
                                        }
                                    }
                                }
                            }
                        } else {
                            Map<String, FieldAttrEntity> fieldAttrEntityMap = paasFormExplainMap.get(formId);
                            if(fieldAttrEntityMap != null){
                                FieldAttrEntity fieldAttrEntity = fieldAttrEntityMap.get(chartFieldAttrPojo.getAttr());
                                if(fieldAttrEntity != null){
                                    SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                                    List<? extends FieldAttrEntity> items = subForm.getItems();
                                    for (FieldAttrEntity v : items) {
                                        if (Objects.equals(v.getAttr(), e.getAttr()) && Objects.equals(v.getIsOpen(), 2)) {
                                            isOpen = false;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if (!isOpen) {
                            return;
                        }

                        if (fieldTypeList.contains(e.getFieldType())) {
                            e.setAttrName(parentSubFormName + "-" + e.getAttrName());
                            e.setAttr(parentSubFormAttr + StringConstant.POINT + e.getAttr());
                            DataSourceObjectVO dataSourceObjectVO = formIdToDataSource.get(formId);
                            if (dataSourceObjectVO == null) {
                                return;
                            }
                            e.setChartId(chartId);
                            dataSourceObjectVO.addFieldListIfAbsent(e);
                        }
                    });
                }
            } else if (Objects.equals(chartFieldType, FieldTypeEnum.ADDRESS.getType())) {
                String attr = chartFieldAttrPojo.getAttr();
                String attrName = chartFieldAttrPojo.getAttrName();
                if (attr.contains(StringConstant.POINT)) {
                    attr = attr.split("\\.")[0];
                    attrName = attrName.split("\\.")[0];
                }
                chartFieldAttrPojo.setAttrName(attrName);
                chartFieldAttrPojo.setAttr(attr);
                String originalAttr = chartFieldAttrPojo.getOriginalAttr();
                if(originalAttr !=null){
                    if (originalAttr.contains(StringConstant.POINT)) {
                        originalAttr = originalAttr.split("\\.")[0];
                        chartFieldAttrPojo.setOriginalAttr(originalAttr);
                    }
                }
            }
            if (!fieldTypeList.contains(chartFieldType)) {
                continue;
            }
            if (Objects.equals(chartFieldAttrPojo.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                Map<String, FieldAttrEntity> fieldAttrEntityMap = workOrderFormExplainMap.get(formId);
                if(fieldAttrEntityMap!=null){
                    String attr = chartFieldAttrPojo.getOriginalAttr()!=null?chartFieldAttrPojo.getOriginalAttr():chartFieldAttrPojo.getAttr();
                    FieldAttrEntity fieldAttrEntity = fieldAttrEntityMap.get(attr);
                    //多平台出现的bug 空指针修复
                    if (fieldAttrEntity != null){
                        if (Objects.equals(fieldAttrEntity.getIsOpen(), 2)) {
                            continue;
                        }
                    }
                }
            } else {
                Map<String, FieldAttrEntity> fieldAttrEntityMap = paasFormExplainMap.get(formId);
                if(fieldAttrEntityMap!=null){
                    String attr = chartFieldAttrPojo.getOriginalAttr()!=null?chartFieldAttrPojo.getOriginalAttr():chartFieldAttrPojo.getAttr();
                    FieldAttrEntity fieldAttrEntity = fieldAttrEntityMap.get(attr);
                    //bug修复   合并分支时需要保留
                    if (fieldAttrEntity != null){
                        if (Objects.equals(fieldAttrEntity.getIsOpen(), 2)) {
                            continue;
                        }
                    }
                }
            }

            DataSourceObjectVO dataSourceObjectVO = formIdToDataSource.get(formId);
            if (dataSourceObjectVO == null) {
                continue;
            }
            chartFieldAttrPojo.setChartId(chartId);
            dataSourceObjectVO.addFieldListIfAbsent(chartFieldAttrPojo);
        }
    }

    private static void getFieldAttrByType(JSONObject fieldAttr, List<Integer> fieldTypeList, Map<Long, DataSourceObjectVO> formIdToDataSource, Long chartId, Map<Long, Map<String, FieldAttrEntity>> paasFormExplainMap, Map<Long, Map<String, FieldAttrEntity>> workOrderFormExplainMap) {
        if (fieldAttr == null) {
            return;
        }
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(fieldAttr);
        getFieldAttrsByType(jsonArray, fieldTypeList, formIdToDataSource, chartId, paasFormExplainMap, workOrderFormExplainMap);
    }

    /**
     * 获取发布配置信息
     * @param configValueArr 发布配置json信息
     * @param categoryPublishDTO 入参
     * @return json
     */
    public static String getConfigValueByPublish(JSONArray configValueArr, CategoryPublishDTO categoryPublishDTO) {
        Integer publish = categoryPublishDTO.getPublish();
        Long categoryId = categoryPublishDTO.getCategoryId();
        String categoryName = categoryPublishDTO.getCategoryName();
        Integer isCustom = categoryPublishDTO.getIsCustom();
        Integer head = categoryPublishDTO.getHead();
        List<HomePagePoJo> userHomePages = configValueArr.toJavaList(HomePagePoJo.class);
        if (Objects.equals(publish, ChartPublishEnum.PUBLISH.getCode())) {
            //发布逻辑
            userHomePages.sort(comparingInt(HomePagePoJo::getSort));
            //取sort值 + 1
            Integer sort = userHomePages.get(userHomePages.size() - 1).getSort() + 1;
            HomePagePoJo homePage = new HomePagePoJo(categoryId, categoryName, sort, 0,isCustom);
            if (Objects.equals(ChartConstant.PUBLISH_HEAD, head)) {
                homePage.setSort(ChartConstant.TAIL_SORT);
                List<HomePagePoJo> tempHomePages = new ArrayList<>();
                tempHomePages.add(homePage);
                tempHomePages.addAll(userHomePages);
                userHomePages = tempHomePages;
             }else {
                userHomePages.add(homePage);
            }
        } else {
            //撤销发布逻辑
            userHomePages.removeIf(homePage -> Objects.equals(homePage.getId(), categoryId) && Objects.equals(isCustom,homePage.getIsCustom()));
            //切换当前第一位置为首页
            userHomePages.get(0).setMain(BasicConstant.ONE);
        }
        return JSONObject.toJSONString(userHomePages);
    }
}
